﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.DirectX.Direct3D;
using System.IO;

namespace SGD_ParticleEditor
{
    public partial class Form1 : Form
    {
        public bool isLooping;
        SGD.ManagedDirect3D d3d;
        SGD.ManagedTextureManager textureManager;
        Emitter emitter;
        int defaultImageID;
        float dt;
        int previousTime;
        string imagePath = null, imageName;
        Blend sourceBlend, destBlend;
        Color bgColor;
        RandomizeWindow randomizeOption = null;

        public Form1()
        {
            InitializeComponent();

            // Init the D3D Wrappers
            d3d = SGD.ManagedDirect3D.Instance;
            d3d.InitManagedDirect3D(DisplayWindow, false);
            textureManager = SGD.ManagedTextureManager.Instance;
            textureManager.InitManagedTextureManager(d3d.Device, d3d.Sprite);

            // Set basic values
            isLooping = true;
            previousTime = System.Environment.TickCount;
            bgColor = Color.FromArgb(255, 0, 0, 0);

            imageName = "Swirl2.png";

            CheckFilePath();

            if (File.Exists(imagePath + imageName))
            {
                defaultImageID = textureManager.LoadTexture(imagePath + imageName, 0);
                emitter = new Emitter(defaultImageID, textureManager.GetTextureWidth(defaultImageID), textureManager.GetTextureHeight(defaultImageID));
            }
            else
            {
                MessageBox.Show("Unable to load texture.");
                emitter = new Emitter(-1, 0, 0);
            }

            // Add it to the Listbox
            ListBox_Emitter.Items.Add(emitter.Name);

            // Get all fields displaying proper information
            SetFieldValues();

            Combo_PlayStyle.SelectedIndex = 0;

            // Emitter Position Bounds
            Ctrl_EmitterXPositionBox.Maximum = Ctrl_EmitterXPosition.Maximum = DisplayWindow.Size.Width;
            Ctrl_EmitterYPositionBox.Maximum = Ctrl_EmitterYPosition.Maximum = DisplayWindow.Size.Height;

            // Emitter Dimensions Bounds
            Ctrl_EmitterRectWidthBox.Maximum = Ctrl_EmitterRectWidth.Maximum = DisplayWindow.Size.Width;
            Ctrl_EmitterRectHeightBox.Maximum = Ctrl_EmitterRectHeight.Maximum = DisplayWindow.Size.Height;

            // Set up blending
            sourceBlend = Blend.SourceAlpha;
            destBlend = Blend.DestinationAlpha;
            Combo_SourceBlend.SelectedIndex = 4;
            Combo_DestBlend.SelectedIndex = 6;
        }

        public void CheckFilePath()
        {
            try
            {
                System.IO.StreamReader reader = new System.IO.StreamReader(Application.StartupPath + "\\relative_path.txt");

                imagePath = reader.ReadLine();

                reader.Close();
            }
            catch
            {
                FolderBrowserDialog dlg = new FolderBrowserDialog();

                bool okButton = false;

                while (!okButton)
                {
                    dlg.Description = "Please select a resource folder location.\nThis location must be set prior to use of this tool.";
                    if (DialogResult.OK == dlg.ShowDialog(this))
                    {
                        imagePath = dlg.SelectedPath + "\\";
                        okButton = true;
                    }
                }
            }
        }

        /// <summary>
        /// Set all control values using the emitter values.
        /// </summary>
        public void SetFieldValues()
        {
            // Number of Particles
            Ctrl_NumParticlesBox.Value = Ctrl_NumParticles.Value = emitter.NumParticles;

            // Lifetime & Variation
            Ctrl_StartLifetime.Value = (int)emitter.LifeTime;
            if (emitter.LifeTime != 0.0f)
            {
                float tempValue = (int)((emitter.LifetimeVariation / emitter.LifeTime) * 100);
                if (tempValue > Ctrl_LifetimeVariation.Maximum)
                    Ctrl_LifetimeVariationBox.Value = Ctrl_LifetimeVariation.Value = Ctrl_LifetimeVariation.Maximum;
                else
                    Ctrl_LifetimeVariationBox.Value = Ctrl_LifetimeVariation.Value = (int)tempValue;
            }
            else
                Ctrl_LifetimeVariationBox.Value = Ctrl_LifetimeVariation.Value = (int)emitter.LifetimeVariation;

            Ctrl_StartLifetimeBox.Value = Ctrl_StartLifetime.Value;

            // Start Scale & Variation
            Ctrl_StartScale.Value = (int)emitter.StartScale;
            if (emitter.StartScale != 0.0f)
            {
                float tempValue = (int)((emitter.StartScaleVariation / emitter.StartScale) * 100);
                if (tempValue > Ctrl_StartScaleVariation.Maximum)
                    Ctrl_StartScaleVariationBox.Value = Ctrl_StartScaleVariation.Value = Ctrl_StartScaleVariation.Maximum;
                else
                    Ctrl_StartScaleVariationBox.Value = Ctrl_StartScaleVariation.Value = (int)tempValue;
            }
            else
                Ctrl_StartScaleVariationBox.Value = Ctrl_StartScaleVariation.Value = (int)emitter.StartScaleVariation;

            Ctrl_StartScaleBox.Value = Ctrl_StartScale.Value;

            // End Scale & Variation
            Ctrl_EndScale.Value = (int)emitter.EndScale;
            if (emitter.EndScale != 0.0f)
            {
                float tempValue = (int)((emitter.EndScaleVariation / emitter.EndScale) * 100);
                if (tempValue > Ctrl_EndScaleVariation.Maximum)
                    Ctrl_EndScaleVariationBox.Value = Ctrl_EndScaleVariation.Value = Ctrl_EndScaleVariation.Maximum;
                else
                    Ctrl_EndScaleVariationBox.Value = Ctrl_EndScaleVariation.Value = (int)tempValue;
            }
            else
                Ctrl_EndScaleVariationBox.Value = Ctrl_EndScaleVariation.Value = (int)emitter.EndScaleVariation;

            Ctrl_EndScaleBox.Value = Ctrl_EndScale.Value;

            // Velocity
            Ctrl_MinXVelocityBox.Value = Ctrl_MinXVelocity.Value = (int)emitter.MinVelocityX;
            Ctrl_MaxXVelocityBox.Value = Ctrl_MaxXVelocity.Value = (int)emitter.MaxVelocityX;
            Ctrl_MinYVelocityBox.Value = Ctrl_MinYVelocity.Value = (int)emitter.MinVelocityY;
            Ctrl_MaxYVelocityBox.Value = Ctrl_MaxYVelocity.Value = (int)emitter.MaxVelocityY;

            // Acceleration
            Ctrl_AccelerationXBox.Value = Ctrl_AccelerationX.Value = (int)emitter.AccelerationX;
            Ctrl_AccelerationYBox.Value = Ctrl_AccelerationY.Value = (int)emitter.AccelerationY;

            // Color - Start
            Ctrl_StartColorA.Value = emitter.StartColor.A;
            Ctrl_StartColorR.Value = emitter.StartColor.R;
            Ctrl_StartColorG.Value = emitter.StartColor.G;
            Ctrl_StartColorB.Value = emitter.StartColor.B;
            Button_StartColor.BackColor = emitter.StartColor;
            Ctrl_StartColorABox.Value = emitter.StartColor.A;
            Ctrl_StartColorRBox.Value = emitter.StartColor.R;
            Ctrl_StartColorGBox.Value = emitter.StartColor.G;
            Ctrl_StartColorBBox.Value = emitter.StartColor.B;

            // Color - End
            Ctrl_EndColorA.Value = emitter.EndColor.A;
            Ctrl_EndColorR.Value = emitter.EndColor.R;
            Ctrl_EndColorG.Value = emitter.EndColor.G;
            Ctrl_EndColorB.Value = emitter.EndColor.B;
            Button_EndColor.BackColor = emitter.EndColor;
            Ctrl_EndColorABox.Value = emitter.EndColor.A;
            Ctrl_EndColorRBox.Value = emitter.EndColor.R;
            Ctrl_EndColorGBox.Value = emitter.EndColor.G;
            Ctrl_EndColorBBox.Value = emitter.EndColor.B;

            // Emitter Position
            Ctrl_EmitterXPositionBox.Value = Ctrl_EmitterXPosition.Value = (int)emitter.PositionX;
            Ctrl_EmitterYPositionBox.Value = Ctrl_EmitterYPosition.Value = (int)emitter.PositionY;

            // Emission Area
            Ctrl_EmitterRectWidthBox.Value = Ctrl_EmitterRectWidth.Value = (int)emitter.Width;
            Ctrl_EmitterRectHeightBox.Value = Ctrl_EmitterRectHeight.Value = (int)emitter.Height;

            // Particle Image Name
            TextBox_ParticleImage.Text = imageName;

            // Emitter Delay Time
            Ctrl_OneShotDelayBox.Value = (decimal)emitter.DelayTime;

            // Blend States
            switch (sourceBlend)
            {
                case Blend.Zero:
                    Combo_SourceBlend.SelectedIndex = 0;
                    break;
                case Blend.One:
                    Combo_SourceBlend.SelectedIndex = 1;
                    break;
                case Blend.SourceColor:
                    Combo_SourceBlend.SelectedIndex = 2;
                    break;
                case Blend.InvSourceColor:
                    Combo_SourceBlend.SelectedIndex = 3;
                    break;
                case Blend.SourceAlpha:
                    Combo_SourceBlend.SelectedIndex = 4;
                    break;
                case Blend.InvSourceAlpha:
                    Combo_SourceBlend.SelectedIndex = 5;
                    break;
                case Blend.DestinationAlpha:
                    Combo_SourceBlend.SelectedIndex = 6;
                    break;
                case Blend.InvDestinationAlpha:
                    Combo_SourceBlend.SelectedIndex = 7;
                    break;
                case Blend.DestinationColor:
                    Combo_SourceBlend.SelectedIndex = 8;
                    break;
                case Blend.InvDestinationColor:
                    Combo_SourceBlend.SelectedIndex = 9;
                    break;
                case Blend.SourceAlphaSat:
                    Combo_SourceBlend.SelectedIndex = 10;
                    break;
                case Blend.BothSourceAlpha:
                    Combo_SourceBlend.SelectedIndex = 11;
                    break;
                case Blend.BothInvSourceAlpha:
                    Combo_SourceBlend.SelectedIndex = 12;
                    break;
                case Blend.BlendFactor:
                    Combo_SourceBlend.SelectedIndex = 13;
                    break;
            }

            switch (destBlend)
            {
                case Blend.Zero:
                    Combo_DestBlend.SelectedIndex = 0;
                    break;
                case Blend.One:
                    Combo_DestBlend.SelectedIndex = 1;
                    break;
                case Blend.SourceColor:
                    Combo_DestBlend.SelectedIndex = 2;
                    break;
                case Blend.InvSourceColor:
                    Combo_DestBlend.SelectedIndex = 3;
                    break;
                case Blend.SourceAlpha:
                    Combo_DestBlend.SelectedIndex = 4;
                    break;
                case Blend.InvSourceAlpha:
                    Combo_DestBlend.SelectedIndex = 5;
                    break;
                case Blend.DestinationAlpha:
                    Combo_DestBlend.SelectedIndex = 6;
                    break;
                case Blend.InvDestinationAlpha:
                    Combo_DestBlend.SelectedIndex = 7;
                    break;
                case Blend.DestinationColor:
                    Combo_DestBlend.SelectedIndex = 8;
                    break;
                case Blend.InvDestinationColor:
                    Combo_DestBlend.SelectedIndex = 9;
                    break;
                case Blend.SourceAlphaSat:
                    Combo_DestBlend.SelectedIndex = 10;
                    break;
                case Blend.BothSourceAlpha:
                    Combo_DestBlend.SelectedIndex = 11;
                    break;
                case Blend.BothInvSourceAlpha:
                    Combo_DestBlend.SelectedIndex = 12;
                    break;
                case Blend.BlendFactor:
                    Combo_DestBlend.SelectedIndex = 13;
                    break;
            }
        }

        /// <summary>
        /// Helper Function - Update the particle image data
        /// </summary>
        public void UpdateParticleImage(string _imageName)
        {
            // Actual Image
            emitter.ImageID = textureManager.LoadTexture(imagePath + _imageName, 0);
            emitter.ImageWidth = textureManager.GetTextureWidth(emitter.ImageID);
            emitter.ImageHeight = textureManager.GetTextureHeight(emitter.ImageID);

            imageName = _imageName;

            // Text box display
            TextBox_ParticleImage.Text = imageName;
        }

        /// <summary>
        /// Handle time ticks and updating of the emitter
        /// </summary>
        public void UpdateSystem()
        {
            int startTime = System.Environment.TickCount;
            dt = (float)((startTime - previousTime) / 1000.0f);
            previousTime = System.Environment.TickCount;

            emitter.Update(dt);
        }

        /// <summary>
        /// Draw the emitter to the screen
        /// </summary>
        public void Render()
        {
            d3d.Clear(bgColor.R, bgColor.G, bgColor.B);

            d3d.DeviceBegin();
            d3d.SpriteBegin();

            d3d.Device.RenderState.SourceBlend = sourceBlend;
            d3d.Device.RenderState.DestinationBlend = destBlend;

            emitter.Render();

            d3d.SpriteEnd();
            d3d.DeviceEnd();

            d3d.Present();
        }

        /// <summary>
        /// When the form is closed, stop the running loop before final termination
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            isLooping = false;

            System.IO.StreamWriter writer = new System.IO.StreamWriter(Application.StartupPath + "\\relative_path.txt");
            writer.WriteLine(imagePath);

            writer.Close();
        }

        // 'New' Menu Option
        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Reset values to default
            emitter = new Emitter(defaultImageID, textureManager.GetTextureWidth(defaultImageID), textureManager.GetTextureHeight(defaultImageID));
            SetFieldValues();

            // Reset blend mode
            sourceBlend = Blend.SourceAlpha;
            destBlend = Blend.DestinationAlpha;
            Combo_SourceBlend.SelectedIndex = 4;
            Combo_DestBlend.SelectedIndex = 6;

            // Reset the listbox
            ListBox_Emitter.Items.Clear();
            ListBox_Emitter.Items.Add(emitter.Name);
        }

        // 'Exit' Menu Option
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        /* Controls - 2 functions per control for Trackbar and NumUpDownBox */

        // Lifetime
        private void Ctrl_StartLifetime_Scroll(object sender, EventArgs e)
        {
            emitter.LifeTime = (float)Ctrl_StartLifetime.Value;
            Ctrl_StartLifetimeBox.Value = Ctrl_StartLifetime.Value;
        }

        private void Ctrl_StartLifetimeBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.LifeTime = (float)Ctrl_StartLifetimeBox.Value;
            Ctrl_StartLifetime.Value = (int)Ctrl_StartLifetimeBox.Value;
        }

        // Lifetime Variation
        //      Note: Converts the percentage from control into a usable number (Ex. 75 in form gets converted to 75% of the StartLife value)
        private void Ctrl_LifetimeVariation_Scroll(object sender, EventArgs e)
        {
            emitter.LifetimeVariation = (float)(Ctrl_StartLifetime.Value - ((Ctrl_LifetimeVariation.Value * 0.01f) * Ctrl_StartLifetime.Value));
            Ctrl_LifetimeVariationBox.Value = Ctrl_LifetimeVariation.Value;
        }

        private void Ctrl_LifetimeVariationBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.LifetimeVariation = (float)((Ctrl_LifetimeVariationBox.Value / 100) * Ctrl_StartLifetimeBox.Value);
            Ctrl_LifetimeVariation.Value = (int)Ctrl_LifetimeVariationBox.Value;
        }

        // Start Scale
        private void Ctrl_StartScale_Scroll(object sender, EventArgs e)
        {
            emitter.StartScale = (float)Ctrl_StartScale.Value;
            Ctrl_StartScaleBox.Value = Ctrl_StartScale.Value;
        }

        private void Ctrl_StartScaleBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.StartScale = (float)Ctrl_StartScaleBox.Value;
            Ctrl_StartScale.Value = (int)Ctrl_StartScaleBox.Value;
        }

        // Start Scale Variation
        //      Note: Converts the percentage from control into a usable number (Ex. 75 in form gets converted to 75% of the StartScale value)
        private void Ctrl_StartScaleVariation_Scroll(object sender, EventArgs e)
        {
            emitter.StartScaleVariation = (float)(Ctrl_StartScale.Value - ((Ctrl_StartScaleVariation.Value * 0.01f) * Ctrl_StartScale.Value));
            Ctrl_StartScaleVariationBox.Value = Ctrl_StartScaleVariation.Value;
        }

        private void Ctrl_StartScaleVariationBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.StartScaleVariation = (float)((Ctrl_StartScaleVariationBox.Value / 100) * Ctrl_StartScaleBox.Value);
            Ctrl_StartScaleVariation.Value = (int)Ctrl_StartScaleVariationBox.Value;
        }

        // End Scale
        private void Ctrl_EndScale_Scroll(object sender, EventArgs e)
        {
            emitter.EndScale = (float)Ctrl_EndScale.Value;
            Ctrl_EndScaleBox.Value = Ctrl_EndScale.Value;
        }

        private void Ctrl_EndScaleBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.EndScale = (float)Ctrl_EndScaleBox.Value;
            Ctrl_EndScale.Value = (int)Ctrl_EndScaleBox.Value;
        }

        // End Scale Variation
        //      Note: Converts the percentage from control into a usable number (Ex. 75 in form gets converted to 75% of the EndScale value)
        private void Ctrl_EndScaleVariation_Scroll(object sender, EventArgs e)
        {
            emitter.EndScaleVariation = (float)(Ctrl_EndScale.Value - ((Ctrl_EndScaleVariation.Value * 0.01f) * Ctrl_EndScale.Value));
            Ctrl_EndScaleVariationBox.Value = Ctrl_EndScaleVariation.Value;
        }

        private void Ctrl_EndScaleVariationBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.EndScaleVariation = (float)((Ctrl_EndScaleVariationBox.Value / 100) * Ctrl_EndScaleBox.Value);
            Ctrl_EndScaleVariation.Value = (int)Ctrl_EndScaleVariationBox.Value;
        }

        // Emitter Image Change Button
        private void Btn_ChangeParticleImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "PNG(*.png)|*.png|Bitmap(*.bmp)|*.bmp|JPEG(*.jpg)|*.jpg|GIF(*.gif)|*.gif";
            dlg.FilterIndex = 1;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                if (dlg.FileName != imagePath + dlg.SafeFileName)
                {
                    MessageBox.Show(Form1.ActiveForm, "Unable to load image. Please load images from\nthe proper resource folder:\n" + imagePath);
                    return;
                }

                UpdateParticleImage(dlg.SafeFileName);
                imageName = dlg.SafeFileName;
            }
        }

        // Emitter X Position
        private void Ctrl_EmitterXPosition_Scroll(object sender, EventArgs e)
        {
            emitter.PositionX = (float)Ctrl_EmitterXPosition.Value;
            Ctrl_EmitterXPositionBox.Value = Ctrl_EmitterXPosition.Value;
        }

        private void Ctrl_EmitterXPositionBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.PositionX = (float)Ctrl_EmitterXPositionBox.Value;
            Ctrl_EmitterXPosition.Value = (int)Ctrl_EmitterXPositionBox.Value;
        }

        // Emitter Y Position
        private void Ctrl_EmitterYPosition_Scroll(object sender, EventArgs e)
        {
            emitter.PositionY = (float)Ctrl_EmitterYPosition.Value;
            Ctrl_EmitterYPositionBox.Value = Ctrl_EmitterYPosition.Value;
        }

        private void Ctrl_EmitterYPositionBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.PositionY = (float)Ctrl_EmitterYPositionBox.Value;
            Ctrl_EmitterYPosition.Value = (int)Ctrl_EmitterYPositionBox.Value;
        }

        private void changeParticleImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "PNG(*.png)|*.png|Bitmap(*.bmp)|*.bmp|JPEG(*.jpg)|*.jpg|GIF(*.gif)|*.gif";
            dlg.FilterIndex = 1;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                if (dlg.FileName != imagePath + dlg.SafeFileName)
                {
                    MessageBox.Show(Form1.ActiveForm, "Unable to load image. Please load images from\nthe proper resource folder:\n" + imagePath);
                    return;
                }

                UpdateParticleImage(dlg.SafeFileName);
                imageName = dlg.SafeFileName;
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;
            dlg.DefaultExt = "xml";

            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement root = new XElement("Emitters");

                // Change this once mulitple emitters are set to the count of the list
                XAttribute xNumEmitters = new XAttribute("Num", 1);
                root.Add(xNumEmitters);

                XElement subElement = new XElement("Emitter");
                root.Add(subElement);

                XAttribute xEmitterName = new XAttribute("Emitter_Name", emitter.Name);
                subElement.Add(xEmitterName);

                XElement xFileName = new XElement("Filename", imageName);
                subElement.Add(xFileName);

                XElement xNumParticles = new XElement("Number_of_Particles", emitter.NumParticles);
                subElement.Add(xNumParticles);

                XElement xLifetime = new XElement("Lifetime", emitter.LifeTime);
                subElement.Add(xLifetime);

                XElement xLifetimeVariation = new XElement("Lifetime_Variation", emitter.LifetimeVariation);
                subElement.Add(xLifetimeVariation);

                XElement xStartScale = new XElement("Start_Scale", emitter.StartScale);
                subElement.Add(xStartScale);

                XElement xStartScaleVariation = new XElement("Start_Scale_Variation", emitter.StartScaleVariation);
                subElement.Add(xStartScaleVariation);

                XElement xEndScale = new XElement("End_Scale", emitter.EndScale);
                subElement.Add(xEndScale);

                XElement xEndScaleVariation = new XElement("End_Scale_Variation", emitter.EndScaleVariation);
                subElement.Add(xEndScaleVariation);

                XElement xMinXVelocity = new XElement("Min_X_Velocity", emitter.MinVelocityX);
                subElement.Add(xMinXVelocity);

                XElement xMaxXVelocity = new XElement("Max_X_Velocity", emitter.MaxVelocityX);
                subElement.Add(xMaxXVelocity);

                XElement xMinYVelocity = new XElement("Min_Y_Velocity", emitter.MinVelocityY);
                subElement.Add(xMinYVelocity);

                XElement xMaxYVelocity = new XElement("Max_Y_Velocity", emitter.MaxVelocityY);
                subElement.Add(xMaxYVelocity);

                XElement xAccelerationX = new XElement("X_Acceleration", emitter.AccelerationX);
                subElement.Add(xAccelerationX);

                XElement xAccelerationY = new XElement("Y_Acceleration", emitter.AccelerationY);
                subElement.Add(xAccelerationY);

                XElement xStartColor = new XElement("Start_Color");
                subElement.Add(xStartColor);

                XAttribute xStartA = new XAttribute("A", emitter.StartColor.A);
                xStartColor.Add(xStartA);

                XAttribute xStartR = new XAttribute("R", emitter.StartColor.R);
                xStartColor.Add(xStartR);

                XAttribute xStartG = new XAttribute("G", emitter.StartColor.G);
                xStartColor.Add(xStartG);

                XAttribute xStartB = new XAttribute("B", emitter.StartColor.B);
                xStartColor.Add(xStartB);

                XElement xEndColor = new XElement("End_Color");
                subElement.Add(xEndColor);

                XAttribute xEndA = new XAttribute("A", emitter.EndColor.A);
                xEndColor.Add(xEndA);

                XAttribute xEndR = new XAttribute("R", emitter.EndColor.R);
                xEndColor.Add(xEndR);

                XAttribute xEndG = new XAttribute("G", emitter.EndColor.G);
                xEndColor.Add(xEndG);

                XAttribute xEndB = new XAttribute("B", emitter.EndColor.B);
                xEndColor.Add(xEndB);

                XElement xPositionX = new XElement("PositionX", emitter.PositionX);
                subElement.Add(xPositionX);

                XElement xPositionY = new XElement("PositionY", emitter.PositionY);
                subElement.Add(xPositionY);

                XElement xWidth = new XElement("Width", emitter.Width);
                subElement.Add(xWidth);

                XElement xHeight = new XElement("Height", emitter.Height);
                subElement.Add(xHeight);

                XElement xSourceBlend = new XElement("Source_Blend", sourceBlend);
                subElement.Add(xSourceBlend);

                XAttribute xSourceIndex = new XAttribute("Index", Combo_SourceBlend.SelectedIndex);
                xSourceBlend.Add(xSourceIndex);

                XElement xDestBlend = new XElement("Destination_Blend", destBlend);
                subElement.Add(xDestBlend);

                XAttribute xDestIndex = new XAttribute("Index", Combo_DestBlend.SelectedIndex);
                xDestBlend.Add(xDestIndex);

                root.Save(dlg.FileName);
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Helper variable for color
            int colorA = 0, colorR = 0, colorG = 0, colorB = 0;

            // Clear the emitter listbox
            ListBox_Emitter.Items.Clear();

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "Xml Files|*.xml";

            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement xRoot = XElement.Load(dlg.FileName);

                IEnumerable<XElement> xEmitter = xRoot.Elements();

                foreach (XElement xEl in xEmitter)
                {
                    XAttribute xEmitterName = xEl.Attribute("Emitter_Name");
                    if (xEmitterName != null)
                    {
                        emitter.Name = xEmitterName.Value;
                        ListBox_Emitter.Items.Add(emitter.Name);
                    }

                    XElement xImageName = xEl.Element("Filename");
                    if (xImageName != null)
                    {
                        if (!File.Exists(imagePath + xImageName.Value))
                        {
                            MessageBox.Show(Form1.ActiveForm, "Unable to load image. Please be sure the specified image is in \nthe proper resource folder:\n" + imagePath);
                            return;
                        }
                        UpdateParticleImage(xImageName.Value);
                    }

                    XElement xNumParticles = xEl.Element("Number_of_Particles");
                    if (xNumParticles != null)
                    {
                        emitter.NumParticles = Convert.ToInt32(xNumParticles.Value);
                    }

                    XElement xLifetime = xEl.Element("Lifetime");
                    if (xLifetime != null)
                    {
                        emitter.LifeTime = (float)Convert.ToDouble(xLifetime.Value);
                    }

                    XElement xLifetimeVariation = xEl.Element("Lifetime_Variation");
                    if (xLifetimeVariation != null)
                    {
                        emitter.LifetimeVariation = (float)Convert.ToDouble(xLifetimeVariation.Value);
                    }

                    XElement xStartScale = xEl.Element("Start_Scale");
                    if (xStartScale != null)
                    {
                        emitter.StartScale = (float)Convert.ToDouble(xStartScale.Value);
                    }

                    XElement xStartScaleVariation = xEl.Element("Start_Scale_Variation");
                    if (xStartScaleVariation != null)
                    {
                        emitter.StartScaleVariation = (float)Convert.ToDouble(xStartScaleVariation.Value);
                    }

                    XElement xEndScale = xEl.Element("End_Scale");
                    if (xEndScale != null)
                    {
                        emitter.EndScale = (float)Convert.ToDouble(xEndScale.Value);
                    }

                    XElement xEndScaleVariation = xEl.Element("End_Scale_Variation");
                    if (xEndScaleVariation != null)
                    {
                        emitter.EndScaleVariation = (float)Convert.ToDouble(xEndScaleVariation.Value);
                    }

                    XElement xMinXVelocity = xEl.Element("Min_X_Velocity");
                    if (xMinXVelocity != null)
                    {
                        emitter.MinVelocityX = (float)Convert.ToDouble(xMinXVelocity.Value);
                    }

                    XElement xMaxXVelocity = xEl.Element("Max_X_Velocity");
                    if (xMaxXVelocity != null)
                    {
                        emitter.MaxVelocityX = (float)Convert.ToDouble(xMaxXVelocity.Value);
                    }

                    XElement xMinYVelocity = xEl.Element("Min_Y_Velocity");
                    if (xMinYVelocity != null)
                    {
                        emitter.MinVelocityY = (float)Convert.ToDouble(xMinYVelocity.Value);
                    }

                    XElement xMaxYVelocity = xEl.Element("Max_Y_Velocity");
                    if (xMaxYVelocity != null)
                    {
                        emitter.MaxVelocityY = (float)Convert.ToDouble(xMaxYVelocity.Value);
                    }

                    XElement xAccelerationX = xEl.Element("X_Acceleration");
                    if (xAccelerationX != null)
                    {
                        emitter.AccelerationX = (float)Convert.ToDouble(xAccelerationX.Value);
                    }

                    XElement xAccelerationY = xEl.Element("Y_Acceleration");
                    if (xAccelerationY != null)
                    {
                        emitter.AccelerationY = (float)Convert.ToDouble(xAccelerationY.Value);
                    }

                    // Element
                    XElement xStartColor = xEl.Element("Start_Color");
                    if (xStartColor != null)
                    {
                        // Attributes
                        XAttribute xStartA = xStartColor.Attribute("A");
                        if (xStartA != null)
                        {
                            colorA = (int)xStartA;
                        }

                        XAttribute xStartR = xStartColor.Attribute("R");
                        if (xStartR != null)
                        {
                            colorR = (int)xStartR;
                        }

                        XAttribute xStartG = xStartColor.Attribute("G");
                        if (xStartG != null)
                        {
                            colorG = (int)xStartG;
                        }

                        XAttribute xStartB = xStartColor.Attribute("B");
                        if (xStartB != null)
                        {
                            colorB = (int)xStartB;
                        }

                        emitter.StartColor = Color.FromArgb(colorA, colorR, colorG, colorB);
                    }

                    // Element
                    XElement xEndColor = xEl.Element("End_Color");
                    if (xEndColor != null)
                    {
                        // Attributes
                        XAttribute xEndA = xEndColor.Attribute("A");
                        if (xEndA != null)
                        {
                            colorA = (int)xEndA;
                        }

                        XAttribute xEndR = xEndColor.Attribute("R");
                        if (xEndR != null)
                        {
                            colorR = (int)xEndR;
                        }

                        XAttribute xEndG = xEndColor.Attribute("G");
                        if (xEndG != null)
                        {
                            colorG = (int)xEndG;
                        }

                        XAttribute xEndB = xEndColor.Attribute("B");
                        if (xEndB != null)
                        {
                            colorB = (int)xEndB;
                        }

                        emitter.EndColor = Color.FromArgb(colorA, colorR, colorG, colorB);
                    }

                    XElement xPositionX = xEl.Element("PositionX");
                    if (xPositionX != null)
                    {
                        emitter.PositionX = (float)Convert.ToDouble(xPositionX.Value);
                    }

                    XElement xPositionY = xEl.Element("PositionY");
                    if (xPositionY != null)
                    {
                        emitter.PositionY = (float)Convert.ToDouble(xPositionY.Value);
                    }

                    XElement xWidth = xEl.Element("Width");
                    if (xWidth != null)
                    {
                        emitter.Width = (float)Convert.ToDouble(xWidth.Value);
                    }

                    XElement xHeight = xEl.Element("Height");
                    if (xHeight != null)
                    {
                        emitter.Height = (float)Convert.ToDouble(xHeight.Value);
                    }

                    XElement xSourceBlend = xEl.Element("Source_Blend");
                    if (xSourceBlend != null)
                    {
                        XAttribute xSourceBlendIndex = xSourceBlend.Attribute("Index");
                        if (xSourceBlendIndex != null)
                        {
                            // Sets the combo box and triggers the changed event to set the actual blend state
                            Combo_SourceBlend.SelectedIndex = (int)xSourceBlendIndex;
                        }
                    }

                    XElement xDestBlend = xEl.Element("Destination_Blend");
                    if (xDestBlend != null)
                    {
                        XAttribute xDestBlendIndex = xDestBlend.Attribute("Index");
                        if (xDestBlendIndex != null)
                        {
                            // Sets the combo box and triggers the changed event to set the actual blend state
                            Combo_DestBlend.SelectedIndex = (int)xDestBlendIndex;
                        }
                    }
                }

                // Update the control fields
                SetFieldValues();
            }
        }

        private void DisplayWindow_MouseDown(object sender, MouseEventArgs e)
        {
            emitter.PositionX = e.X;
            emitter.PositionY = e.Y;

            // Bounds check
            if (emitter.PositionX < 0.0f)
                emitter.PositionX = 0.0f;
            else if (emitter.PositionX > DisplayWindow.Size.Width)
                emitter.PositionX = DisplayWindow.Size.Width;

            // Bounds check
            if (emitter.PositionY < 0.0f)
                emitter.PositionY = 0.0f;
            else if (emitter.PositionY > DisplayWindow.Size.Height)
                emitter.PositionY = DisplayWindow.Size.Height;

            // Update Controls
            Ctrl_EmitterXPositionBox.Value = Ctrl_EmitterXPosition.Value = (int)emitter.PositionX;
            Ctrl_EmitterYPositionBox.Value = Ctrl_EmitterYPosition.Value = (int)emitter.PositionY;
        }

        private void DisplayWindow_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                emitter.PositionX = e.X;
                emitter.PositionY = e.Y;

                // Bounds check
                if (emitter.PositionX < 0.0f)
                    emitter.PositionX = 0.0f;
                else if (emitter.PositionX > DisplayWindow.Size.Width)
                    emitter.PositionX = DisplayWindow.Size.Width;

                // Bounds check
                if (emitter.PositionY < 0.0f)
                    emitter.PositionY = 0.0f;
                else if (emitter.PositionY > DisplayWindow.Size.Height)
                    emitter.PositionY = DisplayWindow.Size.Height;

                // Update Controls
                Ctrl_EmitterXPositionBox.Value = Ctrl_EmitterXPosition.Value = (int)emitter.PositionX;
                Ctrl_EmitterYPositionBox.Value = Ctrl_EmitterYPosition.Value = (int)emitter.PositionY;
            }
        }

        private void DisplayWindow_SizeChanged(object sender, EventArgs e)
        {
            // Emitter Position
            Ctrl_EmitterXPositionBox.Maximum = Ctrl_EmitterXPosition.Maximum = DisplayWindow.Size.Width;
            Ctrl_EmitterYPositionBox.Maximum = Ctrl_EmitterYPosition.Maximum = DisplayWindow.Size.Height;

            // Emitter Dimensions
            Ctrl_EmitterRectWidthBox.Maximum = Ctrl_EmitterRectWidth.Maximum = DisplayWindow.Size.Width;
            Ctrl_EmitterRectHeightBox.Maximum = Ctrl_EmitterRectHeight.Maximum = DisplayWindow.Size.Height;
        }

        private void Combo_PlayStyle_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (Combo_PlayStyle.SelectedIndex == 0)
            {
                emitter.IsContinousPlay = true;
                emitter.IsEmitting = true;
                Label_OneShotDelayTime.Visible = false;
                Ctrl_OneShotDelayBox.Visible = false;
            }
            else
            {
                emitter.IsContinousPlay = false;
                Label_OneShotDelayTime.Visible = true;
                Ctrl_OneShotDelayBox.Visible = true;
            }
        }

        private void Ctrl_OneShotDelayBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.DelayTime = (float)Ctrl_OneShotDelayBox.Value;
        }

        private void randomizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (randomizeOption == null)
            {
                randomizeOption = new RandomizeWindow();

                randomizeOption.Location = new Point(1125, 250);

                randomizeOption.FormClosed += new FormClosedEventHandler(randomizeOption_FormClosed);

                randomizeOption.buttonRandomizeClick += new EventHandler(randomizeOption_buttonRandomizeClick);

                randomizeOption.Show(this);
            }
        }

        void randomizeOption_buttonRandomizeClick(object sender, EventArgs e)
        {
            Random randNum = new Random();
            RandomizeWindow randomTool = (RandomizeWindow)sender;

            if (randomTool.IsNumParticlesChecked)
            {
                emitter.NumParticles = randNum.Next(Ctrl_NumParticles.Minimum, Ctrl_NumParticles.Maximum);
            }

            if (randomTool.IsLifetimeChecked)
            {
                emitter.LifeTime = (float)randNum.NextDouble() * Ctrl_StartLifetime.Maximum;
            }

            if (randomTool.IsLifetimeVariationChecked)
            {
                emitter.LifetimeVariation = (float)randNum.NextDouble() * Ctrl_LifetimeVariation.Maximum;
            }

            if (randomTool.IsStartScaleChecked)
            {
                emitter.StartScale = (float)randNum.NextDouble() * Ctrl_StartScale.Maximum;
            }

            if (randomTool.IsStartScaleVariationChecked)
            {
                emitter.StartScaleVariation = (float)randNum.NextDouble() * Ctrl_StartScaleVariation.Maximum;
            }

            if (randomTool.IsEndScaleChecked)
            {
                emitter.EndScale = (float)randNum.NextDouble() * Ctrl_EndScale.Maximum;
            }

            if (randomTool.IsEndScaleVariationChecked)
            {
                emitter.EndScaleVariation = (float)randNum.NextDouble() * Ctrl_EndScaleVariation.Maximum;
            }

            if (randomTool.IsXVelocityChecked)
            {
                emitter.MinVelocityX = (float)randNum.NextDouble() * Ctrl_MinXVelocity.Maximum;
                emitter.MaxVelocityX = (float)randNum.NextDouble() * Ctrl_MaxXVelocity.Maximum;

                if (randNum.Next(2) == 1)
                    emitter.MinVelocityX *= -1.0f;

                if (randNum.Next(2) == 1)
                    emitter.MaxVelocityX *= -1.0f;
            }

            if (randomTool.IsYVelocityChecked)
            {
                emitter.MinVelocityY = (float)randNum.NextDouble() * Ctrl_MinYVelocity.Maximum;
                emitter.MaxVelocityY = (float)randNum.NextDouble() * Ctrl_MaxYVelocity.Maximum;

                if (randNum.Next(2) == 1)
                    emitter.MinVelocityY *= -1.0f;

                if (randNum.Next(2) == 1)
                    emitter.MaxVelocityY *= -1.0f;
            }

            if (randomTool.IsXAccelerationChecked)
            {
                emitter.AccelerationX = (float)randNum.NextDouble() * Ctrl_AccelerationX.Maximum;

                if (randNum.Next(2) == 1)
                    emitter.AccelerationX *= -1.0f;
            }

            if (randomTool.IsYAccelerationChecked)
            {
                emitter.AccelerationY = (float)randNum.NextDouble() * Ctrl_AccelerationY.Maximum;

                if (randNum.Next(2) == 1)
                    emitter.AccelerationY *= -1.0f;
            }

            if (randomTool.IsStartColorChecked)
            {
                int tempR, tempG, tempB;
                tempR = randNum.Next(0, 255);
                tempG = randNum.Next(0, 255);
                tempB = randNum.Next(0, 255);

                emitter.StartColor = Color.FromArgb(emitter.StartColor.A, tempR, tempG, tempB);
            }

            if (randomTool.IsEndColorChecked)
            {
                int tempR, tempG, tempB;
                tempR = randNum.Next(0, 255);
                tempG = randNum.Next(0, 255);
                tempB = randNum.Next(0, 255);

                emitter.EndColor = Color.FromArgb(emitter.EndColor.A, tempR, tempG, tempB);
            }

            if (randomTool.IsPositionChecked)
            {
                emitter.PositionX = (float)randNum.NextDouble() * Ctrl_EmitterXPosition.Maximum;
                emitter.PositionY = (float)randNum.NextDouble() * Ctrl_EmitterYPosition.Maximum;
            }

            if (randomTool.IsSourceBlendChecked)
            {
                Combo_SourceBlend.SelectedIndex = randNum.Next(0, Combo_SourceBlend.Items.Count - 1);
            }

            if (randomTool.IsDestBlendChecked)
            {
                Combo_DestBlend.SelectedIndex = randNum.Next(0, Combo_DestBlend.Items.Count - 1);
            }

            // Update the controls
            SetFieldValues();
        }

        void randomizeOption_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Window is closed - reset to null
            randomizeOption = null;
        }

        private void Ctrl_MinXVelocity_Scroll(object sender, EventArgs e)
        {
            emitter.MinVelocityX = (float)Ctrl_MinXVelocity.Value;
            Ctrl_MinXVelocityBox.Value = Ctrl_MinXVelocity.Value;
        }

        private void Ctrl_MinXVelocityBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.MinVelocityX = (float)Ctrl_MinXVelocityBox.Value;
            Ctrl_MinXVelocity.Value = (int)Ctrl_MinXVelocityBox.Value;
        }

        private void Ctrl_MaxXVelocity_Scroll(object sender, EventArgs e)
        {
            emitter.MaxVelocityX = (float)Ctrl_MaxXVelocity.Value;
            Ctrl_MaxXVelocityBox.Value = Ctrl_MaxXVelocity.Value;
        }

        private void Ctrl_MaxXVelocityBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.MaxVelocityX = (float)Ctrl_MaxXVelocityBox.Value;
            Ctrl_MaxXVelocity.Value = (int)Ctrl_MaxXVelocityBox.Value;
        }

        private void Ctrl_MinYVelocity_Scroll(object sender, EventArgs e)
        {
            emitter.MinVelocityY = (float)Ctrl_MinYVelocity.Value;
            Ctrl_MinYVelocityBox.Value = Ctrl_MinYVelocity.Value;
        }

        private void Ctrl_MinYVelocityBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.MinVelocityY = (float)Ctrl_MinYVelocityBox.Value;
            Ctrl_MinYVelocity.Value = (int)Ctrl_MinYVelocityBox.Value;
        }

        private void Ctrl_MaxYVelocity_Scroll(object sender, EventArgs e)
        {
            emitter.MaxVelocityY = (float)Ctrl_MaxYVelocity.Value;
            Ctrl_MaxYVelocityBox.Value = Ctrl_MaxYVelocity.Value;
        }

        private void Ctrl_MaxYVelocityBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.MaxVelocityY = (float)Ctrl_MaxYVelocityBox.Value;
            Ctrl_MaxYVelocity.Value = (int)Ctrl_MaxYVelocityBox.Value;
        }

        private void Ctrl_EmitterRectWidth_Scroll(object sender, EventArgs e)
        {
            emitter.Width = (float)Ctrl_EmitterRectWidth.Value;
            emitter.WidthOffset = emitter.Width / 2;
            Ctrl_EmitterRectWidthBox.Value = Ctrl_EmitterRectWidth.Value;
        }

        private void Ctrl_EmitterRectWidthBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.Width = (float)Ctrl_EmitterRectWidthBox.Value;
            emitter.WidthOffset = emitter.Width / 2;
            Ctrl_EmitterRectWidth.Value = (int)Ctrl_EmitterRectWidthBox.Value;
        }

        private void Ctrl_EmitterRectHeight_Scroll(object sender, EventArgs e)
        {
            emitter.Height = (float)Ctrl_EmitterRectHeight.Value;
            emitter.HeightOffset = emitter.Height / 2;
            Ctrl_EmitterRectHeightBox.Value = Ctrl_EmitterRectHeight.Value;
        }

        private void Ctrl_EmitterRectHeightBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.Height = (float)Ctrl_EmitterRectHeightBox.Value;
            emitter.HeightOffset = emitter.Height / 2;
            Ctrl_EmitterRectHeight.Value = (int)Ctrl_EmitterRectHeightBox.Value;
        }

        private void changeBackgroundColorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog dlg = new ColorDialog();

            if (DialogResult.OK == dlg.ShowDialog())
            {
                bgColor = dlg.Color;
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            About dlg = new About();

            if (DialogResult.OK == dlg.ShowDialog()) { }
        }

        private void ChangeEmitterName_Click(object sender, EventArgs e)
        {
            EmitterName dlg = new EmitterName();

            if (DialogResult.OK == dlg.ShowDialog())
            {
                if (ListBox_Emitter.SelectedIndex != -1)
                {
                    emitter.Name = dlg.NewName;
                    ListBox_Emitter.Items[ListBox_Emitter.SelectedIndex] = emitter.Name;
                }
            }
        }

        private void Ctrl_AccelerationX_Scroll(object sender, EventArgs e)
        {
            emitter.AccelerationX = (float)Ctrl_AccelerationX.Value;
            Ctrl_AccelerationXBox.Value = Ctrl_AccelerationX.Value;
        }

        private void Ctrl_AccelerationXBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.AccelerationX = (float)Ctrl_AccelerationXBox.Value;
            Ctrl_AccelerationX.Value = (int)Ctrl_AccelerationXBox.Value;
        }

        private void Ctrl_AccelerationY_Scroll(object sender, EventArgs e)
        {
            emitter.AccelerationY = (float)Ctrl_AccelerationY.Value;
            Ctrl_AccelerationYBox.Value = Ctrl_AccelerationY.Value;
        }

        private void Ctrl_AccelerationYBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.AccelerationY = (float)Ctrl_AccelerationYBox.Value;
            Ctrl_AccelerationY.Value = (int)Ctrl_AccelerationYBox.Value;
        }

        private void Ctrl_NumParticles_Scroll(object sender, EventArgs e)
        {
            emitter.NumParticles = Ctrl_NumParticles.Value;
            Ctrl_NumParticlesBox.Value = Ctrl_NumParticles.Value;
        }

        private void Ctrl_NumParticlesBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.NumParticles = (int)Ctrl_NumParticlesBox.Value;
            Ctrl_NumParticles.Value = (int)Ctrl_NumParticlesBox.Value;
        }

        // Start Alpha
        private void Ctrl_StartColorA_Scroll(object sender, EventArgs e)
        {
            emitter.StartColor = Color.FromArgb(Ctrl_StartColorA.Value, Ctrl_StartColorR.Value, Ctrl_StartColorG.Value, Ctrl_StartColorB.Value);
            Ctrl_StartColorABox.Value = Ctrl_StartColorA.Value;
            Button_StartColor.BackColor = emitter.StartColor;
        }

        private void Ctrl_StartColorABox_ValueChanged(object sender, EventArgs e)
        {
            emitter.StartColor = Color.FromArgb((int)Ctrl_StartColorABox.Value, Ctrl_StartColorR.Value, Ctrl_StartColorG.Value, Ctrl_StartColorB.Value);
            Ctrl_StartColorA.Value = (int)Ctrl_StartColorABox.Value;
            Button_StartColor.BackColor = emitter.StartColor;
        }

        // Start Red
        private void Ctrl_StartColorR_Scroll(object sender, EventArgs e)
        {
            emitter.StartColor = Color.FromArgb(Ctrl_StartColorA.Value, Ctrl_StartColorR.Value, Ctrl_StartColorG.Value, Ctrl_StartColorB.Value);
            Ctrl_StartColorRBox.Value = Ctrl_StartColorR.Value;
            Button_StartColor.BackColor = emitter.StartColor;
        }

        private void Ctrl_StartColorRBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.StartColor = Color.FromArgb(Ctrl_StartColorA.Value, (int)Ctrl_StartColorRBox.Value, Ctrl_StartColorG.Value, Ctrl_StartColorB.Value);
            Ctrl_StartColorR.Value = (int)Ctrl_StartColorRBox.Value;
            Button_StartColor.BackColor = emitter.StartColor;
        }

        // Start Green
        private void Ctrl_StartColorG_Scroll(object sender, EventArgs e)
        {
            emitter.StartColor = Color.FromArgb(Ctrl_StartColorA.Value, Ctrl_StartColorR.Value, Ctrl_StartColorG.Value, Ctrl_StartColorB.Value);
            Ctrl_StartColorGBox.Value = Ctrl_StartColorG.Value;
            Button_StartColor.BackColor = emitter.StartColor;
        }

        private void Ctrl_StartColorGBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.StartColor = Color.FromArgb(Ctrl_StartColorA.Value, Ctrl_StartColorR.Value, (int)Ctrl_StartColorGBox.Value, Ctrl_StartColorB.Value);
            Ctrl_StartColorG.Value = (int)Ctrl_StartColorGBox.Value;
            Button_StartColor.BackColor = emitter.StartColor;
        }

        // Start Blue
        private void Ctrl_StartColorB_Scroll(object sender, EventArgs e)
        {
            emitter.StartColor = Color.FromArgb(Ctrl_StartColorA.Value, Ctrl_StartColorR.Value, Ctrl_StartColorG.Value, Ctrl_StartColorB.Value);
            Ctrl_StartColorBBox.Value = Ctrl_StartColorB.Value;
            Button_StartColor.BackColor = emitter.StartColor;
        }

        private void Ctrl_StartColorBBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.StartColor = Color.FromArgb(Ctrl_StartColorA.Value, Ctrl_StartColorR.Value, Ctrl_StartColorG.Value, (int)Ctrl_StartColorBBox.Value);
            Ctrl_StartColorB.Value = (int)Ctrl_StartColorBBox.Value;
            Button_StartColor.BackColor = emitter.StartColor;
        }

        // End Alpha
        private void Ctrl_EndColorA_Scroll(object sender, EventArgs e)
        {
            emitter.EndColor = Color.FromArgb(Ctrl_EndColorA.Value, Ctrl_EndColorR.Value, Ctrl_EndColorG.Value, Ctrl_EndColorB.Value);
            Ctrl_EndColorABox.Value = Ctrl_EndColorA.Value;
            Button_EndColor.BackColor = emitter.EndColor;
        }

        private void Ctrl_EndColorABox_ValueChanged(object sender, EventArgs e)
        {
            emitter.EndColor = Color.FromArgb((int)Ctrl_EndColorABox.Value, Ctrl_EndColorR.Value, Ctrl_EndColorG.Value, Ctrl_EndColorB.Value);
            Ctrl_EndColorA.Value = (int)Ctrl_EndColorABox.Value;
            Button_EndColor.BackColor = emitter.EndColor;
        }

        // End Red
        private void Ctrl_EndColorR_Scroll(object sender, EventArgs e)
        {
            emitter.EndColor = Color.FromArgb(Ctrl_EndColorA.Value, Ctrl_EndColorR.Value, Ctrl_EndColorG.Value, Ctrl_EndColorB.Value);
            Ctrl_EndColorRBox.Value = Ctrl_EndColorR.Value;
            Button_EndColor.BackColor = emitter.EndColor;
        }

        private void Ctrl_EndColorRBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.EndColor = Color.FromArgb(Ctrl_EndColorA.Value, (int)Ctrl_EndColorRBox.Value, Ctrl_EndColorG.Value, Ctrl_EndColorB.Value);
            Ctrl_EndColorR.Value = (int)Ctrl_EndColorRBox.Value;
            Button_EndColor.BackColor = emitter.EndColor;
        }

        // End Green
        private void Ctrl_EndColorG_Scroll(object sender, EventArgs e)
        {
            emitter.EndColor = Color.FromArgb(Ctrl_EndColorA.Value, Ctrl_EndColorR.Value, Ctrl_EndColorG.Value, Ctrl_EndColorB.Value);
            Ctrl_EndColorGBox.Value = Ctrl_EndColorG.Value;
            Button_EndColor.BackColor = emitter.EndColor;
        }

        private void Ctrl_EndColorGBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.EndColor = Color.FromArgb(Ctrl_EndColorA.Value, Ctrl_EndColorR.Value, (int)Ctrl_EndColorGBox.Value, Ctrl_EndColorB.Value);
            Ctrl_EndColorG.Value = (int)Ctrl_EndColorGBox.Value;
            Button_EndColor.BackColor = emitter.EndColor;
        }

        // End Blue
        private void Ctrl_EndColorB_Scroll(object sender, EventArgs e)
        {
            emitter.EndColor = Color.FromArgb(Ctrl_EndColorA.Value, Ctrl_EndColorR.Value, Ctrl_EndColorG.Value, Ctrl_EndColorB.Value);
            Ctrl_EndColorBBox.Value = Ctrl_EndColorB.Value;
            Button_EndColor.BackColor = emitter.EndColor;
        }

        private void Ctrl_EndColorBBox_ValueChanged(object sender, EventArgs e)
        {
            emitter.EndColor = Color.FromArgb(Ctrl_EndColorA.Value, Ctrl_EndColorR.Value, Ctrl_EndColorG.Value, (int)Ctrl_EndColorBBox.Value);
            Ctrl_EndColorB.Value = (int)Ctrl_EndColorBBox.Value;
            Button_EndColor.BackColor = emitter.EndColor;
        }

        // Start Color Button
        private void Button_StartColor_Click(object sender, EventArgs e)
        {
            ColorDialog currColor = new ColorDialog();

            // Sets the current color
            currColor.Color = emitter.StartColor;

            // 'OK' is pressed
            if (DialogResult.OK == currColor.ShowDialog())
            {
                emitter.StartColor = currColor.Color;

                Button_StartColor.BackColor = currColor.Color;

                // Set other Control values
                Ctrl_StartColorRBox.Value = Ctrl_StartColorR.Value = currColor.Color.R;
                Ctrl_StartColorGBox.Value = Ctrl_StartColorG.Value = currColor.Color.G;
                Ctrl_StartColorBBox.Value = Ctrl_StartColorB.Value = currColor.Color.B;
            }
        }

        // End Color Button
        private void Button_EndColor_Click(object sender, EventArgs e)
        {
            ColorDialog currColor = new ColorDialog();

            // Set the current color
            currColor.Color = emitter.EndColor;

            // 'OK' is pressed
            if (DialogResult.OK == currColor.ShowDialog())
            {
                emitter.EndColor = currColor.Color;

                Button_EndColor.BackColor = currColor.Color;

                // Set other Control values
                Ctrl_EndColorRBox.Value = Ctrl_EndColorR.Value = currColor.Color.R;
                Ctrl_EndColorGBox.Value = Ctrl_EndColorG.Value = currColor.Color.G;
                Ctrl_EndColorBBox.Value = Ctrl_EndColorB.Value = currColor.Color.B;
            }
        }

        private void Combo_SourceBlend_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (Combo_SourceBlend.SelectedIndex)
            {
                case 0:
                    sourceBlend = Blend.Zero;
                    break;
                case 1:
                    sourceBlend = Blend.One;
                    break;
                case 2:
                    sourceBlend = Blend.SourceColor;
                    break;
                case 3:
                    sourceBlend = Blend.InvSourceColor;
                    break;
                case 4:
                    sourceBlend = Blend.SourceAlpha;
                    break;
                case 5:
                    sourceBlend = Blend.InvSourceAlpha;
                    break;
                case 6:
                    sourceBlend = Blend.DestinationAlpha;
                    break;
                case 7:
                    sourceBlend = Blend.InvDestinationAlpha;
                    break;
                case 8:
                    sourceBlend = Blend.DestinationColor;
                    break;
                case 9:
                    sourceBlend = Blend.InvDestinationColor;
                    break;
                case 10:
                    sourceBlend = Blend.SourceAlphaSat;
                    break;
                case 11:
                    sourceBlend = Blend.BothSourceAlpha;
                    break;
                case 12:
                    sourceBlend = Blend.BothInvSourceAlpha;
                    break;
                case 13:
                    sourceBlend = Blend.BlendFactor;
                    break;
            }
        }

        private void Combo_DestBlend_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (Combo_DestBlend.SelectedIndex)
            {
                case 0:
                    destBlend = Blend.Zero;
                    break;
                case 1:
                    destBlend = Blend.One;
                    break;
                case 2:
                    destBlend = Blend.SourceColor;
                    break;
                case 3:
                    destBlend = Blend.InvSourceColor;
                    break;
                case 4:
                    destBlend = Blend.SourceAlpha;
                    break;
                case 5:
                    destBlend = Blend.InvSourceAlpha;
                    break;
                case 6:
                    destBlend = Blend.DestinationAlpha;
                    break;
                case 7:
                    destBlend = Blend.InvDestinationAlpha;
                    break;
                case 8:
                    destBlend = Blend.DestinationColor;
                    break;
                case 9:
                    destBlend = Blend.InvDestinationColor;
                    break;
                case 10:
                    destBlend = Blend.SourceAlphaSat;
                    break;
                case 11:
                    destBlend = Blend.BothSourceAlpha;
                    break;
                case 12:
                    destBlend = Blend.BothInvSourceAlpha;
                    break;
                case 13:
                    destBlend = Blend.BlendFactor;
                    break;
            }
        }
    }
}